package com.chinawayltd.ews.sample.service.algorithm.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.chinawayltd.ews.sample.mapper.TDriverMapper;
import com.chinawayltd.ews.sample.mapper.TDriverPlanMapper;
import com.chinawayltd.ews.sample.mapper.TLogMapper;
import com.chinawayltd.ews.sample.mapper.TShiftMapper;
import com.chinawayltd.ews.sample.mapper.TVehicleMapper;
import com.chinawayltd.ews.sample.mapper.algorithm.DriverExtendMapper;
import com.chinawayltd.ews.sample.mapper.algorithm.DriverPlanExtendMapper;
import com.chinawayltd.ews.sample.mapper.basicInfo.ShiftExtendMapper;
import com.chinawayltd.ews.sample.model.TDriver;
import com.chinawayltd.ews.sample.model.TDriverExample;
import com.chinawayltd.ews.sample.model.TDriverPlan;
import com.chinawayltd.ews.sample.model.TDriverPlanExample;
import com.chinawayltd.ews.sample.model.TLog;
import com.chinawayltd.ews.sample.model.TShift;
import com.chinawayltd.ews.sample.model.TShiftExample;
import com.chinawayltd.ews.sample.model.TVehicle;
import com.chinawayltd.ews.sample.model.TVehicleExample;
import com.chinawayltd.ews.sample.model.TVehicleExample.Criteria;
import com.chinawayltd.ews.sample.model.algorithm.DriverPlanVO;
import com.chinawayltd.ews.sample.model.algorithm.DriverWorkVO;
import com.chinawayltd.ews.sample.service.algorithm.DriverPlanService;
import com.chinawayltd.ews.sample.service.base.impl.BaseServiceImpl;
import com.chinawayltd.ews.sample.util.PageData;
import com.chinawayltd.ews.sample.util.StringUtils;
import com.chinawayltd.ews.sample.util.excel.ExcelObjModel;
import com.chinawayltd.ews.sample.util.excel.ExportCloumsModel;
import com.chinawayltd.ews.sample.web.query.DriverGirdQuery;
import com.chinawayltd.ews.sample.web.query.DriverPlanGirdQuery;

/**
 * @program: greeProject
 * @description 实现类
 * @author: chenxin
 * @create: 2018年4月11日 下午10:50:03
 */
@Service
public class DriverPlanServiceImpl extends BaseServiceImpl implements DriverPlanService {
	private static final SimpleDateFormat HHMM = new SimpleDateFormat("HH:mm");
	private static final String tableName = "T_DRIVER_PLAN";

	@Autowired
	private TDriverPlanMapper tDriverPlanMapper;
	@Autowired
	private DriverPlanExtendMapper driverPlanExtendMapper;
	@Autowired
	private DriverExtendMapper driverExtendMapper;
	@Autowired
	private TLogMapper tLogMapper;
	@Autowired
	private TDriverMapper tDriverMapper;
	@Autowired
	private TVehicleMapper tVehicleMapper;
	@Autowired
	private TShiftMapper tShiftMapper;
	@Autowired
	private ShiftExtendMapper shiftExtendMapper;

	@Override
	public List<DriverPlanVO> listDriverPlanByPage(DriverPlanGirdQuery queryParam) {
		return driverPlanExtendMapper.listDriverPlanByPage(queryParam);
	}

	@Override
	public TDriverPlan getById(Long id) throws Exception{
		if (id == null || id <= 0) {
			throw new RuntimeException("id不能为空或者少于等于0！");
		}
		return tDriverPlanMapper.selectByPrimaryKey(id);
	}

	@Override
	public int add(TDriverPlan tDriverPlan) {
		tDriverPlan.setCreateTime(new Date());
		int result = driverPlanExtendMapper.insert(tDriverPlan);
		if(result >0){
    		TLog log = new TLog();
    		log.setDataId(tDriverPlan.getId());
    		log.setTableName(tableName);
    		log.setOperationUser(getCurrentUser().getRealname());
    		log.setOperationType(1);
    		log.setCreateTime(new Date());
    		tLogMapper.insert(log);
        }
		return result;
		
	}

	@Override
	public int update(TDriverPlan tDriverPlan) {
		tDriverPlan.setUpdateTime(new Date());
		int result = tDriverPlanMapper.updateByPrimaryKeySelective(tDriverPlan);
		if(result >0){
    		TLog log = new TLog();
    		log.setDataId(tDriverPlan.getId());
    		log.setTableName(tableName);
    		log.setOperationUser(getCurrentUser().getRealname());
    		log.setOperationType(2);
    		log.setCreateTime(new Date());
    		tLogMapper.insert(log);
        }
		return result;
		
	}

	@Override
	public int delete(Long id) throws Exception{
		if (id == null || id <= 0) {
			throw new RuntimeException("id不能为空或者少于等于0！");
		}
		return tDriverPlanMapper.deleteByPrimaryKey(id);
	}

	@Override
	public List<TDriverPlan> listAll() {
		return tDriverPlanMapper.selectByExample(null);
	}

	@Override
	public List<TDriverPlan> listDriverPlanByShiftId(Long shiftId) throws Exception{
		if(shiftId == null || shiftId <= 0){
            throw new RuntimeException("id不能为空或者少于等于0！");
        }
		return driverPlanExtendMapper.listDriverPlanById(shiftId);
	}

	@Override
	public int deletesByIds(String[] ids) {
		return driverPlanExtendMapper.deleteAll(ids);
	}

	@Override
	public ExcelObjModel insertList(List<PageData> list){
		ExcelObjModel model = new ExcelObjModel();
		List<Object> mapList = new ArrayList<>();
		model.setCode(0); // 0没添加1添加成功，否则有添加不成功的
		int result = 0;
		Date now = new Date();

		// 遍历读取的Excel数据，判断数据的正确性
		for (PageData pd : list) {
			try {
				DriverPlanVO driverPlanVO = new DriverPlanVO();
				// 司机名称
				String driverName = pd.getString("var0");
				driverPlanVO.setDriverName(driverName);
				// 车牌号
				String carNum = pd.getString("var1");
				driverPlanVO.setCarNum(carNum);
				// 班次名称
				String shiftName = pd.getString("var2");
				driverPlanVO.setShiftName(shiftName);

				// 将对象转化为map，判断是否为空
				Map<String, Object> map = com.chinawayltd.ews.sample.util.MapUtils.objectToMap(driverPlanVO);
				if (StringUtils.isBlank(driverName) || StringUtils.isBlank(carNum) || StringUtils.isBlank(shiftName)) {
					map.put("describe", "填写的字段不能为空");
					mapList.add(map);
					continue;
				}
				// 判断司机是否存在
				Map<String, Object> judgeDriverNameExist = judgeDriverNameExist(driverName);
				if (org.apache.commons.collections4.MapUtils.getInteger(judgeDriverNameExist, "flag") == 1) {
					driverPlanVO
							.setDriverId(org.apache.commons.collections4.MapUtils.getLong(judgeDriverNameExist, "id"));
				} else {
					map.put("describe", "司机不存在");
					mapList.add(map);
					continue;
				}
				// 判断车辆是否存在
				Map<String, Object> judgeCarNumExist = judgeCarNumExist(carNum);
				if (org.apache.commons.collections4.MapUtils.getInteger(judgeCarNumExist, "flag") == 1) {
					driverPlanVO.setCarId(org.apache.commons.collections4.MapUtils.getLong(judgeCarNumExist, "id"));
				} else {
					map.put("describe", "车牌不存在");
					mapList.add(map);
					continue;
				}
				// 判断班次
				Map<String, Object> judgeDriverShift = judgeDriverShift(shiftName);
				if (org.apache.commons.collections4.MapUtils.getInteger(judgeDriverShift, "flag") == 1) {
					driverPlanVO.setShiftId(org.apache.commons.collections4.MapUtils.getLong(judgeDriverShift, "id"));
				} else if (org.apache.commons.collections4.MapUtils.getInteger(judgeDriverShift, "flag") == 0) {
					map.put("describe", org.apache.commons.collections4.MapUtils.getString(judgeDriverShift, "error"));
					mapList.add(map);
					continue;
				}
				driverPlanVO.setCreateTime(now);
				driverPlanVO.setUpdateTime(now);
				// TODO 导入数据
				Map<String, Object> resultMap = this.toLeadData(driverPlanVO);
				if (org.apache.commons.collections4.MapUtils.getInteger(resultMap, "result") > 0) {
					map.put("describe", org.apache.commons.collections4.MapUtils.getString(resultMap, "describe"));
					mapList.add(map);
				} else {
					map.put("describe", org.apache.commons.collections4.MapUtils.getString(resultMap, "describe"));
					mapList.add(map);
					continue;
				}

				model.setCode(result);
			} catch (Exception e) {
				e.printStackTrace();
				model.setCode(0);
				Map<String, Object> exceptionMap = new HashMap<>();
				exceptionMap.put("driverName", pd.getString("var0"));
				exceptionMap.put("carNum", pd.getString("var1"));
				exceptionMap.put("shiftName", pd.getString("var2"));
				exceptionMap.put("describe", "数据异常，导入失败");
				mapList.add(exceptionMap);
			}
		}

		model.setList(mapList);
		List<ExportCloumsModel> cloums = new ArrayList<>();
		if (mapList.size() > 0) {
			cloums.add(new ExportCloumsModel("司机名称", "driverName"));
			cloums.add(new ExportCloumsModel("车牌号", "carNum"));
			cloums.add(new ExportCloumsModel("班次名称", "shiftName"));
			cloums.add(new ExportCloumsModel("导入描述", "describe"));
		}
		model.setCloums(cloums);
		return model;
	}

	/**
	 * 导入数据,判断是否有数据冲突
	 * 
	 * @author Fay
	 * @date 2018年5月7日 下午3:56:40
	 * @param driverPlanVO
	 * @return
	 */
	private Map<String, Object> toLeadData(DriverPlanVO driverPlanVO) {
		int result = 0;
		Map<String, Object> resultMap = new HashMap<>();

		TDriverPlanExample example = new TDriverPlanExample();
		com.chinawayltd.ews.sample.model.TDriverPlanExample.Criteria createCriteria = example.createCriteria();
		// 如果3项都重复 则不处理
		createCriteria.andDriverIdEqualTo(driverPlanVO.getDriverId());
		createCriteria.andCarIdEqualTo(driverPlanVO.getCarId());
		createCriteria.andShiftIdEqualTo(driverPlanVO.getShiftId());
		List<TDriverPlan> selectByExample_1 = tDriverPlanMapper.selectByExample(example);
		if (selectByExample_1.size() > 0) {
			resultMap.put("result", result);
			resultMap.put("describe", "数据重复");
		} else {
			TShift shift = tShiftMapper.selectByPrimaryKey(driverPlanVO.getShiftId());
			// 判断司机时间是否冲突
			boolean judgeTimeConflict = this.judgeTimeConflict(shift, driverPlanVO.getDriverId(), driverPlanVO.getId());
			
			if (judgeTimeConflict) {
				resultMap.put("result", 0);// 0:错误 1:成功
				resultMap.put("describe", "该司机已排班");
				return resultMap;
			} 
			
			boolean judgeCarTimeConflict = this.judgeCarTimeConflict(shift, driverPlanVO.getCarId(), driverPlanVO.getCarId());
			if(judgeCarTimeConflict){
				resultMap.put("result", 0);// 0:错误 1:成功
				resultMap.put("describe", "该车辆在该班次时段已关联了司机");
				return resultMap;
			}
			// 不冲突则新增
			result = driverPlanExtendMapper.insert(driverPlanVO);
			resultMap.put("result", result);
			resultMap.put("describe", "导入成功");
			if (result > 0) {
				TLog log = new TLog();
				log.setDataId(driverPlanVO.getId());
				log.setTableName(tableName);
				log.setOperationUser(getCurrentUser().getRealname());
				log.setOperationType(1);
				log.setCreateTime(new Date());
				log.setUpdateTime(new Date());
				tLogMapper.insert(log);
			}
		}
		return resultMap;
	}

	/**判断车辆是否与班次时间冲突
	 * @author Fay
	 * @date 2018年5月23日 下午4:03:23
	 * @param shift
	 * @param carId
	 * @param carId2
	 * @return
	 */
	private boolean judgeCarTimeConflict(TShift shift, Long carId, Long planId) {
		try {
			String bigTime_ = shift.getBigTime();
			String endTime_ = shift.getEndTime();
			String id_ = planId != null ? planId.toString() : "";
			List<Map<String,Object>> carPlanList = driverPlanExtendMapper.getCarPlanTimeIsConflict(carId, id_);
			if (carPlanList.size() > 0) {
				for (Map<String, Object> shiftMap : carPlanList) {
					String bigTime = MapUtils.getString(shiftMap, "big_time");
					String endTime = MapUtils.getString(shiftMap, "end_time");
					Date bigDate = HHMM.parse(bigTime);
					Date endDate = HHMM.parse(endTime);
					Date bigDate_ = HHMM.parse(bigTime_);
					Date endDate_ = HHMM.parse(endTime_);
					if (bigDate_.compareTo(endDate_) < 0) {// 传参的时间是正常的，开始时间小于结束时间
						boolean flag = this.executeTimeJudgment(bigDate_, endDate_, bigDate, endDate);
						if (flag) {
							return true;
						}
					} else if (bigDate_.compareTo(endDate_) > 0) {// 传参时间有过度，如18:00-06:00
						// 先用24小时来换算,如18:00-23:59 00:00-06:00
						Date endDateTran_ = HHMM.parse("23:59");
						boolean flag_1 = this.executeTimeJudgment(bigDate_, endDateTran_, bigDate, endDate);
						Date bigDateTran_ = HHMM.parse("00:00");
						boolean flag_2 = this.executeTimeJudgment(bigDateTran_, endDate_, bigDate, endDate);
						if (flag_1 || flag_2) {
							return true;
						}
					}
				}
			}
		} catch (ParseException e) {
			e.printStackTrace();
			return true;// 存在冲突
		}
		return false;
	}

	/**
	 * 新增班次设定
	 * 
	 * @author Fay
	 * @date 2018年5月3日 下午6:10:58
	 * @param driverPlanVO
	 * @param endTime
	 * @param bigTime
	 */
	private Long insertDriverShift(DriverPlanVO driverPlanVO, String bigTime, String endTime) {
		TShift tShift = new TShift();
		tShift.setCreateTime(new Date());
		tShift.setUpdateTime(new Date());
		tShift.setShiftName(driverPlanVO.getShiftName());
		tShift.setShiftType((byte) Integer.valueOf(driverPlanVO.getShiftType()).intValue());
		tShift.setBigTime(bigTime);
		tShift.setEndTime(endTime);

		int insert = shiftExtendMapper.insert(tShift);
		if (insert > 0) {
			TLog log = new TLog();
			log.setDataId(tShift.getId());
			log.setTableName(tableName);
			log.setOperationUser(getCurrentUser().getRealname());
			log.setOperationType(1);
			log.setCreateTime(new Date());
			log.setUpdateTime(new Date());
			tLogMapper.insert(log);
		}

		return tShift.getId();
	}

	/**
	 * 判断排班信息是否存在
	 * 
	 * @author Fay
	 * @date 2018年5月3日 下午2:37:49
	 * @param shiftName
	 * @param shiftType
	 * @param bigTime
	 * @param endTime
	 * @return
	 */
	private Map<String, Object> judgeDriverShift(String shiftName) {
		Map<String, Object> resultModel = new HashMap<>();
		TShiftExample example = new TShiftExample();
		example.createCriteria().andShiftNameEqualTo(shiftName);
		List<TShift> shiftList = tShiftMapper.selectByExample(example);
		if (shiftList.size() > 0) {
			TShift tShift = shiftList.get(0);
			resultModel.put("flag", 1);
			resultModel.put("id", tShift.getId());
			return resultModel;
		} else {
			// 如果不存在
			resultModel.put("flag", 0);
			resultModel.put("error", "班次不存在");
			return resultModel;
		}
	}

	/**
	 * 判断司机名是否存在
	 * 
	 * @author Fay
	 * @date 2018年5月3日 下午2:16:50
	 * @param driverName
	 * @return
	 */
	private Map<String, Object> judgeDriverNameExist(String driverName) {
		Map<String, Object> resultModel = new HashMap<>();

		TDriverExample example = new TDriverExample();
		com.chinawayltd.ews.sample.model.TDriverExample.Criteria criteria = example.createCriteria();
		criteria.andDriverNameEqualTo(driverName);
		List<TDriver> driverList = tDriverMapper.selectByExample(example);
		if (driverList.size() > 0) {
			// 如果存在
			// 如果获取的数据List只有一条证明只有一条站点信息，如果有多条证明有重复的数据，那也就只拿第一条数据
			Long id = driverList.get(0).getId();
			resultModel.put("id", id);
			resultModel.put("flag", 1);
			return resultModel;
		} else {
			// 如果不存在
			resultModel.put("flag", 0);
			return resultModel;
		}
	}

	/**
	 * 判断车牌是否存在
	 * 
	 * @author Fay
	 * @date 2018年5月3日 下午2:28:53
	 * @param driverName
	 * @return
	 */
	private Map<String, Object> judgeCarNumExist(String carNum) {
		Map<String, Object> resultModel = new HashMap<>();

		TVehicleExample example = new TVehicleExample();
		Criteria criteria = example.createCriteria();
		criteria.andCarNumEqualTo(carNum);
		List<TVehicle> vehicleList = tVehicleMapper.selectByExample(example);
		if (vehicleList.size() > 0) {
			// 如果存在
			// 如果获取的数据List只有一条证明只有一条站点信息，如果有多条证明有重复的数据，那也就只拿第一条数据
			Long vehicleId = vehicleList.get(0).getId();
			resultModel.put("id", vehicleId);
			resultModel.put("flag", 1);
			return resultModel;
		} else {
			// 如果不存在
			resultModel.put("flag", 0);
			return resultModel;
		}
	}

	@Override
	public boolean judgeDriverShiftConflict(TDriverPlan tDriverPlan) {
		TShift shift = tShiftMapper.selectByPrimaryKey(tDriverPlan.getShiftId());
		// 判断司机添加的班次是否矛盾
		// 查询该司机是否有别的班次，如果为0表示没冲突
		boolean conflict = judgeTimeConflict(shift, tDriverPlan.getDriverId(), tDriverPlan.getId());
		boolean conflict1 = judgeCarTimeConflict(shift, tDriverPlan.getCarId(), tDriverPlan.getId());
		if (conflict || conflict1) {
			return true;//冲突
		}
		return false;
	}
	
	/**判断司机是否与班次冲突，同时一个司机只有一个班次
	 * @author Fay
	 * @date 2018年5月28日 下午1:11:44
	 * @param shift
	 * @param driverId
	 * @param planId
	 * @return
	 */
	private boolean judgeTimeConflict(TShift shift, Long driverId, Long planId) {
		try {
			String bigTime_ = shift.getBigTime();
			String endTime_ = shift.getEndTime();
			String id_ = planId != null ? planId.toString() : "";
			List<Map<String,Object>> driverPlanList = driverPlanExtendMapper.getDriverPlanTimeIsConflict(driverId, id_);
			if (driverPlanList.size() > 0) {
				/*for (Map<String, Object> shiftMap : driverPlanList) {
					String bigTime = MapUtils.getString(shiftMap, "big_time");
					String endTime = MapUtils.getString(shiftMap, "end_time");
					Date bigDate = HHMM.parse(bigTime);
					Date endDate = HHMM.parse(endTime);
					Date bigDate_ = HHMM.parse(bigTime_);
					Date endDate_ = HHMM.parse(endTime_);
					if (bigDate_.compareTo(endDate_) < 0) {// 传参的时间是正常的，开始时间小于结束时间
						boolean flag = this.executeTimeJudgment(bigDate_, endDate_, bigDate, endDate);
						if (flag) {
							return true;
						}
					} else if (bigDate_.compareTo(endDate_) > 0) {// 传参时间有过度，如18:00-06:00
						// 先用24小时来换算,如18:00-23:59 00:00-06:00
						Date endDateTran_ = HHMM.parse("23:59");
						boolean flag_1 = this.executeTimeJudgment(bigDate_, endDateTran_, bigDate, endDate);
						Date bigDateTran_ = HHMM.parse("00:00");
						boolean flag_2 = this.executeTimeJudgment(bigDateTran_, endDate_, bigDate, endDate);
						if (flag_1 || flag_2) {
							return true;
						}
					}
				}*/
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return true;// 存在冲突
		}
		return false;
	}

	/**
	 * @author Fay
	 * @date 2018年5月23日 上午11:36:30
	 * @param bigDate_ 传参过来的开始时间
	 * @param endDate_ 传参过来的结束时间
	 * @param bigDate 查数据库的开始时间
	 * @param endDate 查数据库的结束时间
	 * @return true 有冲突 false 无冲突
	 */
	private boolean JudgeDateWhetherOrNotConflict(Date bigDate_, Date endDate_, Date bigDate, Date endDate) {
		if ((bigDate_.compareTo(bigDate) > 0 || bigDate_.compareTo(bigDate) == 0) && bigDate_.compareTo(endDate) < 0) {
			return true;
		} else if ((endDate_.compareTo(endDate) < 0 || endDate_.compareTo(endDate) == 0)
				&& endDate_.compareTo(bigDate) > 0) {
			return true;
		}
		return false;
	}

	/**
	 * @author Fay
	 * @date 2018年5月23日 上午11:48:44
	 * @param bigDate_ 传参过来的开始时间
	 * @param endDate_ 传参过来的结束时间
	 * @param bigDate 查数据库的开始时间
	 * @param endDate 查数据库的结束时间
	 * @return true 有冲突 false 无冲突
	 * @throws ParseException
	 */
	private boolean executeTimeJudgment(Date bigDate_, Date endDate_, Date bigDate, Date endDate)
			throws ParseException {
		if (bigDate.compareTo(endDate) < 0) {// 正常开始时间是小于结束时间，判断传入的参数是否与此时间段相交
			return this.JudgeDateWhetherOrNotConflict(bigDate_, endDate_, bigDate, endDate);
		} else if (bigDate.compareTo(endDate) > 0) {// 如果查数据库时间为18:00-06:00
			// 先用24小时来换算,如18:00-23:59 00:00-06:00
			Date endDateTran = HHMM.parse("23:59");
			boolean flag_1 = this.JudgeDateWhetherOrNotConflict(bigDate_, endDate_, bigDate, endDateTran);
			Date bigDateTran = HHMM.parse("00:00");
			boolean flag_2 = this.JudgeDateWhetherOrNotConflict(bigDate_, endDate_, bigDateTran, endDate);
			if (flag_1 || flag_2) {
				return true;
			}
		}
		return false;
	}

	@Override
	public List<TDriverPlan> getByIdAndName(String id, String name) {
		return driverPlanExtendMapper.getByIdAndName(id, name);
	}

	@Override
	public List<DriverWorkVO> driverContinueWorkGirdData(DriverGirdQuery queryParam) {
		if(StringUtils.isBlank(queryParam.getSortStr())){
			queryParam.setSortStr("updateTime DESC");
		}
		return driverExtendMapper.driverContinueWorkGirdData(queryParam);
	}

	@Override
	public int driverExtendUpdate(Long id) throws Exception{
		if (id == null || id <= 0) {
			throw new RuntimeException("id不能为空或者少于等于0！");
		}
		return driverExtendMapper.driverExtendUpdate(id);
	}
    
}
